home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 7: Sunsite / Linux Cubed Series 7 - Sunsite Vol 1.iso / system / emulator / bsvc-1.000 / bsvc-1 / bsvc-1.0.4 / src / Assemblers / 68kasm / movem.c < prev    next >
C/C++ Source or Header  |  1995-07-26  |  9KB  |  332 lines

  1. /******************************************************************************
  2.  * $Id: movem.c,v 1.1 1994/08/30 00:06:33 bmott Exp $
  3.  ******************************************************************************
  4.  *
  5.  *        MOVEM.C
  6.  *        Routines for the MOVEM instruction and the REG directive
  7.  *
  8.  *    Function: movem()
  9.  *        Builds MOVEM instructions. The size of the instruction
  10.  *        is given by the size argument (assumed to be word if 
  11.  *        not specified). The label argument points to the label 
  12.  *        appearing on the source line containing the MOVEM 
  13.  *        instruction, if any, and the op argument points to the
  14.  *        operands of the MOVEM instruction. The routine returns
  15.  *        an error code in *errorPtr by the standard mechanism. 
  16.  *
  17.  *        reg()
  18.  *        Defines a special register list symbol to be used as an
  19.  *        argument for the MOVEM instruction. The size argument
  20.  *        reflects the size code appended to the REG directive,
  21.  *        which should be empty. The label argument points to the
  22.  *        label appearing on the source line containing the REG
  23.  *        directive (which must be specified), and the op
  24.  *        argument points to a register list which is the new
  25.  *        value of the symbol. The routine returns an error code
  26.  *        in *errorPtr by the standard mechanism. 
  27.  *
  28.  *     Usage:    movem(size, label, op, errorPtr)
  29.  *        int size;
  30.  *        char *label, *op;
  31.  *        int *errorPtr;
  32.  *
  33.  *        reg(size, label, op, errorPtr)
  34.  *        int size;
  35.  *        char *label, *op;
  36.  *        int *errorPtr;
  37.  *
  38.  *      Author: Paul McKee
  39.  *        ECE492    North Carolina State University
  40.  *
  41.  *        Date:    12/9/86
  42.  *
  43.  *   Copyright 1990-1991 North Carolina State University. All Rights Reserved.
  44.  *
  45.  ******************************************************************************
  46.  * $Log: movem.c,v $
  47.  * Revision 1.1  1994/08/30  00:06:33  bmott
  48.  * Initial revision
  49.  *
  50.  *****************************************************************************/
  51.  
  52.  
  53. #include <stdio.h>
  54. #include <ctype.h>
  55. #include "asm.h"
  56.  
  57.  
  58. /* Define bit masks for the legal addressing modes of MOVEM */
  59.  
  60. #define ControlAlt  (AnInd | AnIndDisp | AnIndIndex | AbsShort | AbsLong)
  61. #define DestModes   (ControlAlt | AnIndPre)
  62. #define SourceModes (ControlAlt | AnIndPost | PCDisp | PCIndex)
  63.  
  64.  
  65. extern int loc;
  66. extern char pass2;
  67. char *evalList();
  68.  
  69.  
  70. movem(size, label, op, errorPtr)
  71. int size;
  72. char *label, *op;
  73. int *errorPtr;
  74. {
  75. char *p, *opParse();
  76. int status;
  77. unsigned short regList, temp, instMask;
  78. char i;
  79. opDescriptor memOp;
  80. symbolDef *define();
  81.  
  82.     /* Pick mask according to size code (only .W and .L are valid) */
  83.     if (size == WORD)
  84.         instMask = 0x4880;
  85.     else if (size == LONG)
  86.         instMask = 0x48C0;
  87.     else {
  88.         if (size)
  89.             NEWERROR(*errorPtr, INV_SIZE_CODE);
  90.         instMask = 0x4880;
  91.         }
  92.     /* Define the label attached to this instruction */
  93.     if (*label)
  94.         define(label, loc, pass2, errorPtr);
  95.  
  96.     /* See if the instruction is of the form MOVEM <reg_list>,<ea> */
  97.     status = OK;
  98.     /* Parse the register list */
  99.     p = evalList(op, ®List, &status);
  100.     if (status == OK && *p == ',') {
  101.         /* Parse the memory address */
  102.         p = opParse(++p, &memOp, &status);
  103.         NEWERROR(*errorPtr, status);
  104.         if (status < ERROR) {
  105.             /* Check legality of addressing mode */
  106.             if (memOp.mode & DestModes) {
  107.                 /* It's good, now generate the instruction */
  108.                 if (pass2) {
  109.                     output(instMask | effAddr(&memOp), WORD);
  110.                     loc += 2;
  111.                     /* If the addressing mode is address
  112.                        register indirect with predecrement,
  113.                        reverse the bits in the register 
  114.                        list mask */
  115.                     if (memOp.mode == AnIndPre) {
  116.                         temp = regList;
  117.                         regList = 0;
  118.                         for (i = 0; i < 16; i++) {
  119.                             regList <<= 1;
  120.                             regList |= (temp & 1);
  121.                             temp >>= 1;
  122.                             }
  123.                         }
  124.                     output(regList, WORD);
  125.                     loc += 2;
  126.                     }
  127.                 else
  128.                     loc += 4;
  129.                 extWords(&memOp, errorPtr);
  130.                 return;
  131.                 }
  132.             else {
  133.                 NEWERROR(*errorPtr, INV_ADDR_MODE);
  134.                 return;
  135.                 }
  136.             }
  137.         }
  138.  
  139.     /* See if the instruction is of the form MOVEM <ea>,<reg_list> */
  140.     status = OK;    
  141.     /* Parse the effective address */
  142.     p = opParse(op, &memOp, &status);
  143.     NEWERROR(*errorPtr, status);
  144.     if (status < ERROR && *p == ',') {
  145.         /* Check the legality of the addressing mode */
  146.         if (memOp.mode & SourceModes) {
  147.             /* Parse the register list */
  148.             status = OK;
  149.             p = evalList(++p, ®List, &status);
  150.             if (status == OK) {
  151.                 /* Everything's OK, now build the instruction */
  152.                 if (pass2) {
  153.                     output(instMask | 0x0400 | effAddr(&memOp), WORD);
  154.                     loc += 2;
  155.                     output(regList, WORD);
  156.                     loc += 2;
  157.                     }
  158.                 else
  159.                     loc += 4;
  160.                 extWords(&memOp);
  161.                 return;
  162.                 }
  163.             }
  164.         else {
  165.             NEWERROR(*errorPtr, INV_ADDR_MODE);
  166.             return;
  167.             }
  168.         }
  169.  
  170.     /* If the instruction isn't of either form, then return an error */
  171.     NEWERROR(*errorPtr, status);    
  172. }
  173.  
  174.  
  175. reg(size, label, op, errorPtr)
  176. int size;
  177. char *label, *op;
  178. int *errorPtr;
  179. {
  180. int value, backRef, status;
  181. symbolDef *symbol, *define();
  182. unsigned short regList;
  183.  
  184.     if (size)
  185.         NEWERROR(*errorPtr, INV_SIZE_CODE);
  186.     if (!*op) {
  187.         NEWERROR(*errorPtr, SYNTAX);
  188.         return;
  189.         }
  190.     op = evalList(op, ®List, errorPtr);
  191.     if (*errorPtr < SEVERE)
  192.         if (!*label) {
  193.             NEWERROR(*errorPtr, LABEL_REQUIRED);
  194.             }
  195.         else {
  196.             status = OK;    
  197.             symbol = define(label, regList, pass2, &status);
  198.             NEWERROR(*errorPtr, status);
  199.             if (status < ERROR)
  200.                 symbol->flags |= REG_LIST_SYM;
  201.             }
  202. }
  203.  
  204.  
  205. /* Define a couple of useful tests */
  206.  
  207. #define isTerm(c)   (c == ',' || c == '/' || c == '-' || isspace(c) || !c)
  208. #define isRegNum(c) ((c >= '0') && (c <= '7'))
  209.  
  210.  
  211. char *evalList(p, listPtr, errorPtr)
  212. char *p;
  213. unsigned short *listPtr;
  214. int *errorPtr;
  215. {
  216. char reg1, reg2, r;
  217. unsigned short regList;
  218. char symName[SIGCHARS+1];
  219. char i;
  220. symbolDef *symbol, *lookup();
  221. int status;
  222.  
  223.     regList = 0;
  224.     /* Check whether the register list is specified
  225.        explicitly or as a register list symbol */
  226.     if ((p[0] == 'A' || p[0] == 'D') && isRegNum(p[1]) && isTerm(p[2])) {
  227.         /* Assume it's explicit */
  228.         while (TRUE) {    /* Loop will be exited via return */
  229.             if ((p[0] == 'A' || p[0] == 'D') && isRegNum(p[1])) {
  230.                 if (p[0] == 'A')
  231.                     reg1 = 8 + p[1] - '0';
  232.                 else
  233.                     reg1 = p[1] - '0';
  234.                 if (p[2] == '/') {
  235.                     /* Set the bit the for a single register */
  236.                     regList |= (1 << reg1);
  237.                     p += 3;
  238.                     }
  239.                 else if (p[2] == '-')
  240.                     if ((p[3] == 'A' || p[3] == 'D') && isRegNum(p[4]) && isTerm(p[5])) {
  241.                         if (p[5] == '-') {
  242.                             NEWERROR(*errorPtr, SYNTAX);
  243.                             return NULL;
  244.                             }
  245.                         if (p[3] == 'A')
  246.                             reg2 = 8 + p[4] - '0';
  247.                         else
  248.                             reg2 = p[4] - '0';
  249.                         /* Set all the bits corresponding to registers 
  250.                            in the specified range */
  251.                         if (reg1 < reg2)
  252.                             for (r = reg1; r <= reg2; r++)
  253.                                 regList |= (1 << r);
  254.                         else
  255.                             for (r = reg2; r <= reg1; r++)
  256.                                 regList |= (1 << r);
  257.                         if (p[5] != '/') {
  258.                             /* End of register list found - return its value */
  259.                             *listPtr = regList;
  260.                             return p+5;
  261.                             }
  262.                         p += 6;
  263.                         }
  264.                     else {
  265.                         /* Invalid character found - return the error */
  266.                         NEWERROR(*errorPtr, SYNTAX);
  267.                         return NULL;
  268.                         }
  269.                 else {
  270.                     /* Set the bit the for a single register */
  271.                     regList |= (1 << reg1);
  272.                     /* End of register list found - return its value */
  273.                     *listPtr = regList;
  274.                     return p+2;
  275.                     }
  276.                 }
  277.             else {
  278.                 /* Invalid character found - return the error */
  279.                 NEWERROR(*errorPtr, SYNTAX);
  280.                 return NULL;
  281.                 }
  282.             }
  283.         }
  284.     else {
  285.         /* Try looking in the symbol table for a register list symbol */
  286.         if (!isalpha(*p) && *p != '.') {
  287.             NEWERROR(*errorPtr, SYNTAX);
  288.             return NULL;
  289.             }
  290.         i = 0;
  291.         /* Collect characters of the symbol's name
  292.            (only SIGCHARS characters are significant) */
  293.         do {
  294.             if (i < SIGCHARS)
  295.                 symName[i++] = *p;
  296.             p++;
  297.         } while (isalnum(*p) || *p == '.' || *p == '_' || *p == '$');
  298.         /* Check for invalid syntax */
  299.         if (!isspace(*p) && *p != ',' && *p) {
  300.             NEWERROR(*errorPtr, SYNTAX);
  301.             return NULL;
  302.             }
  303.         symName[i] = '\0';
  304.         /* Look up the name in the symbol table, resulting
  305.            in a pointer to the symbol table entry */
  306.         status = OK;
  307.         symbol = lookup(symName, FALSE, &status);
  308.         if (status < SEVERE)
  309.             /* The register list symbol must be
  310.                previously defined in the program */
  311.             if (status == UNDEFINED) {
  312.                 NEWERROR(*errorPtr, status);
  313.                 }
  314.             else if (pass2 && !(symbol->flags & BACKREF)) {
  315.                 NEWERROR(*errorPtr, REG_LIST_UNDEF);
  316.                 }
  317.             else {
  318.                 if (symbol->flags & REG_LIST_SYM)
  319.                     *listPtr = symbol->value;
  320.                 else {
  321.                     NEWERROR(*errorPtr, NOT_REG_LIST);
  322.                     *listPtr = 0x1234;
  323.                     }
  324.                 }
  325.         else {
  326.             NEWERROR(*errorPtr, status);
  327.             *listPtr = 0;
  328.             }
  329.         return p;
  330.         }
  331. }
  332.